package com.medusa.aps.business.modules.basic.mp.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.medusa.aps.business.model.constant.RedisConstants;
import com.medusa.aps.business.model.enums.SourceEnum;
import com.medusa.aps.business.model.pagination.Page;
import com.medusa.aps.business.modules.basic.model.input.CustomerInformationDTO;
import com.medusa.aps.business.modules.basic.model.input.CustomerInformationParam;
import com.medusa.aps.business.modules.basic.mp.entity.CustomerInformation;
import com.medusa.aps.business.modules.basic.mp.mapper.CustomerInformationMapper;
import com.medusa.aps.business.modules.basic.mp.service.CustomerInformationService;
import com.medusa.aps.business.modules.demand.mp.entity.OrderInformation;
import com.medusa.aps.business.modules.demand.mp.service.OrderInformationService;
import com.medusa.aps.business.util.ExcelUtils;
import com.medusa.aps.business.util.PercentageScheduleUtils;
import com.medusa.aps.business.common.model.resp.SystemCode;
import com.medusa.aps.business.common.redis.annotation.Redisson;
import com.medusa.aps.business.global.model.exception.GlobalException;
import com.medusa.aps.business.global.model.exception.collector.DistinctValidator;
import com.medusa.aps.business.global.model.exception.collector.ErrorCollector;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * 客户信息服务实现类
 *
 * @author yuxh
 * @since 2023-08-14 17:37:43
 */
@Service("customerInformationService")
public class CustomerInformationServiceImpl extends ServiceImpl<CustomerInformationMapper, CustomerInformation> implements CustomerInformationService {


    @Resource
    public OrderInformationService orderInformationService;
    @Resource
    private CustomerInformationService customerInformationService;

    /**
     * 分页查询客户信息
     *
     * @param customerInformationParam 分页对象
     * @return 客户信息分页数据
     */
    @Override
    public Page<CustomerInformation> pageCustomerInformation(CustomerInformationParam customerInformationParam) {
        return customerInformationService.lambdaQuery()
                .in(CollUtil.isNotEmpty(customerInformationParam.getIds()), CustomerInformation::getId, customerInformationParam.getIds())
                .like(StrUtil.isNotBlank(customerInformationParam.getCustomerCode()), CustomerInformation::getCustomerCode, customerInformationParam.getCustomerCode())
                .like(StrUtil.isNotBlank(customerInformationParam.getCustomerName()), CustomerInformation::getCustomerName, customerInformationParam.getCustomerName())
                .like(StrUtil.isNotBlank(customerInformationParam.getCustomerCompanyName()), CustomerInformation::getCustomerCompanyName, customerInformationParam.getCustomerCompanyName())
                .between(customerInformationParam.getCreateTime().getStartTime() != null && customerInformationParam.getCreateTime().getEndTime() != null,
                        CustomerInformation::getCreateTime,
                        customerInformationParam.getCreateTime().getStartTime(),
                        customerInformationParam.getCreateTime().getEndTime())
                .orderByDesc(CustomerInformation::getCreateTime)
                .page(customerInformationParam);
    }

    /**
     * 批量新增客户
     *
     * @param customerInformationDTOS 客户信息集合
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @Redisson(name = RedisConstants.CUSTOMER_INFORMATION_LOCK_KEY, waitTime = 1)
    public void saveBatchCustomerInformation(List<CustomerInformationDTO> customerInformationDTOS) {
        validatorParam(customerInformationDTOS);
        List<CustomerInformation> customers = customerInformationDTOS.stream()
                .map(customerInformationDTO -> new CustomerInformation()
                        .setCustomerCode(customerInformationDTO.getCustomerCode())
                        .setCustomerName(customerInformationDTO.getCustomerName())
                        .setCustomerPhone(customerInformationDTO.getCustomerPhone())
                        .setCustomerCompanyName(customerInformationDTO.getCustomerCompanyName())
                        .setCustomerPriority(customerInformationDTO.getCustomerPriority())
                        .setDataSource(SourceEnum.ARTIFICIAL)
                ).toList();
        customerInformationService.saveBatch(customers);
    }


    /**
     * 修改数据客户信息
     *
     * @param customerInformationDTO 客户信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @Redisson(name = RedisConstants.CUSTOMER_INFORMATION_LOCK_KEY, waitTime = 1)
    public void updateCustomerInformation(CustomerInformationDTO customerInformationDTO) {
        CustomerInformation customer = customerInformationService.lambdaQuery().eq(CustomerInformation::getId, customerInformationDTO.getId()).one();
        if (customer == null) {
            throw SystemCode.PARAM_VALID_ERROR.msgEx("该客户已不存在");
        }
        customer.setCustomerName(customerInformationDTO.getCustomerName())
                .setCustomerPhone(customerInformationDTO.getCustomerPhone())
                .setCustomerCompanyName(customerInformationDTO.getCustomerCompanyName())
                .setCustomerPriority(customerInformationDTO.getCustomerPriority());
        customerInformationService.updateById(customer);
    }

    private void validatorParam(List<CustomerInformationDTO> customerInformationDTOS) {
        ErrorCollector errorCollector = DistinctValidator.valid(customerInformationDTOS, CustomerInformationDTO::getCustomerCode, "客户编码");
        if (errorCollector.hasError()) {
            throw new GlobalException(errorCollector.toString());
        }
        List<String> customerCodes = customerInformationDTOS.stream().map(CustomerInformationDTO::getCustomerCode).toList();
        Set<String> customerCodeDbs = customerInformationService.lambdaQuery()
                .select(CustomerInformation::getCustomerCode)
                .in(CustomerInformation::getCustomerCode, customerCodes)
                .list().stream()
                .map(CustomerInformation::getCustomerCode)
                .collect(Collectors.toSet());
        if (CollUtil.isEmpty(customerCodeDbs)) {
            return;
        }
        Map<Long, StringBuilder> errorMap = new TreeMap<>();
        for (int i = 0; i < customerCodes.size(); i++) {
            String customerCode = customerCodes.get(i);
            if (customerCodeDbs.contains(customerCode)) {
                ExcelUtils.handlerErrorMessage(errorMap, i + 1L, StrUtil.format("客户编码【{}】系统已存在", customerCode));
            }
        }
        ExcelUtils.validErrorMessageData(errorMap);
    }

    /**
     * 根据客户编码或客户名称查询客户基本信息
     *
     * @return 客户基本信息集合
     */
    @Override
    public List<CustomerInformation> getCustomerInformation(String customerCode, String customerName, String customerCompanyName) {
        return customerInformationService.lambdaQuery()
                .select(
                        CustomerInformation::getId, CustomerInformation::getCustomerCode, CustomerInformation::getCustomerName,
                        CustomerInformation::getCustomerCompanyName, CustomerInformation::getCustomerPhone, CustomerInformation::getCustomerPriority
                )
                .like(StrUtil.isNotBlank(customerCode), CustomerInformation::getCustomerCode, customerCode)
                .like(StrUtil.isNotBlank(customerName), CustomerInformation::getCustomerName, customerName)
                .like(StrUtil.isNotBlank(customerCompanyName), CustomerInformation::getCustomerCompanyName, customerCompanyName)
                .last("limit 500")
                .list();
    }

    @Override
    @Redisson(name = RedisConstants.CUSTOMER_INFORMATION_LOCK_KEY, waitTime = 1)
    public void delete(Set<Long> ids) {
        List<CustomerInformation> customerInformations = customerInformationService.lambdaQuery()
                .select(CustomerInformation::getCustomerCode, CustomerInformation::getCustomerName)
                .in(CustomerInformation::getId, ids)
                .list();
        if (CollectionUtils.isEmpty(customerInformations)) {
            throw new GlobalException("客户信息不存在");
        }
        List<String> customerCodes = customerInformations.stream().map(CustomerInformation::getCustomerCode).toList();
        PercentageScheduleUtils.valid(
                orderInformationService.lambdaQuery()
                        .select(OrderInformation::getCustomerCode)
                        .in(OrderInformation::getCustomerCode, customerCodes)
                        .list(),
                OrderInformation::getCustomerCode,
                "客户编码:【{}】下有需求订单,暂不支持删除"
        );

        customerInformationService.removeBatchByIds(ids);
    }

}


